package com.mg.pluginexample3;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;

import com.mg.model.Module;
import com.mg.model.Param;
import com.mg.model.Port;
import com.mg.model.Model.LogLevel;
import com.mg.pluginexample1.DataTablePort;

public class TempMoudle extends Module{

	public TempMoudle(int nID) {
		super(nID);
		m_alInputPort.add(new DataTablePort(this,Port.Type.Unknown));
		m_alOutputPort.add(new Port(this,Port.Type.Unknown));
		m_llResult = new ArrayList<String>();
		m_eCS = ChooseStation.Last;
	}
	
	public String GetGroupName()
	{
		return "JDBC";
	}
	public String GetName()
	{
		return "查找最近国家站点";
	}
	public String GetDescription()
	{
		return "";
	}
	public boolean OnAttach(Port portFrom, Port portTo)
	{
		try
		{
			int i = FindPort(portFrom, false);
			if (i != -1)
				return true;
			i = FindPort(portTo, true);
			if (i == -1)
				return false;
			
			ArrayList<Param> alParam = new ArrayList<Param>();
			portFrom.GetModule().GetOutputParam(portFrom, alParam);
			if (alParam.size() != 1)
				return false;
			if (alParam.get(0).m_objValue != null && !(alParam.get(0).m_objValue instanceof ResultSet) && !(alParam.get(0).m_objValue instanceof List<?>))
				return false;
			portTo.SetType(portFrom.GetType());
			DataTablePort dtp = (DataTablePort)portTo;
			if (alParam.get(0).m_objValue instanceof List<?>)
				dtp.m_list = (List<String>)alParam.get(0).m_objValue;
			else if (alParam.get(0).m_objValue instanceof ResultSet)
				dtp.m_rs = (ResultSet)alParam.get(0).m_objValue;
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
			return false;
		}
		return true;
	}
	
	public int GetParam (ArrayList<Param> alParam)
	{
		try
		{
			alParam.add(new Param("StationNum",m_strStationNum,"站号","","字段",Param.EditType.Default));
			alParam.add(new Param("LongiTude",m_strLongiTude,"X","","字段",Param.EditType.Default));
			alParam.add(new Param("LatiTude",m_strLatiTude,"Y","","字段",Param.EditType.Default));
			alParam.add(new Param("Hight",m_strHight,"H","","字段",Param.EditType.Default));
			//////////////////////////////////////////////////////////////////////////////////////////
			alParam.add(new Param("Style",m_eCS.toString(),"选站规则","距离最近","筛选方式",Param.EditType.Select,"Last|TowOrThree"));
			alParam.add(new Param("BaseNum",String.valueOf(m_iNum),"站数","","筛选方式",m_eCS == ChooseStation.Last? Param.EditType.ReadOnly:Param.EditType.Default));
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return alParam.size();
	}
	
	public int SetParam(final ArrayList<Param> alParam)
	{
		int i = super.GetParam(alParam);
		try
		{
			m_strStationNum = (String)alParam.get(i++).m_objValue;
			m_strLongiTude = (String)alParam.get(i++).m_objValue;
			m_strLatiTude = (String)alParam.get(i++).m_objValue;
			m_strHight = (String)alParam.get(i++).m_objValue;
			
			m_eCS = ChooseStation.valueOf((String)alParam.get(i++).m_objValue);
			m_iNum = Integer.valueOf((String)alParam.get(i++).m_objValue);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return i;
	}
	
	public boolean OnParamChanged(ArrayList<Param> alParam,int nIndex, Object objValue)
	{
		if (alParam.get(nIndex).m_strName.equalsIgnoreCase("Style"))
		{
			alParam.get(nIndex+1).m_eEditType = Param.EditType.ReadOnly;
			if (((String)objValue).equals("Last"))
				alParam.get(nIndex).m_strDescription = "距离最近";
			else
			{
				alParam.get(nIndex).m_strDescription = "海拔相差最小";
				alParam.get(nIndex+1).m_eEditType = Param.EditType.Default;
			}
		}
		alParam.get(nIndex).m_objValue = objValue;
		return true;
	}
	
	public ArrayList<StationInfo> GetData(Port pt, int index)
	{
		if (pt != null)
		{
			ArrayList<StationInfo> alStationInfo = new ArrayList<StationInfo>();
			
			try
			{
				int i= -1,x = -1,y = -1,h = -1,nStationNum =-1;
				String str ="";
				DataTablePort dtp = (DataTablePort)pt;
				ResultSetMetaData rsmd = dtp.m_rs != null ? dtp.m_rs.getMetaData() : null;
				String[] strs = dtp.m_list != null ? dtp.m_list.get(0).split(",") : null;
				
				for (i = 0; i < (rsmd != null ? rsmd.getColumnCount() : strs.length); i++)
				{
					str = (rsmd != null ? rsmd.getColumnLabel(i + 1) : strs[i]);
					if (str.equalsIgnoreCase("StationNum"))
						nStationNum = i;
					else if (str.equalsIgnoreCase("X"))
						x = i;
					else if (str.equalsIgnoreCase("Y"))
						y = i;
					else if (str.equalsIgnoreCase("H"))
						h = i;
				}
				if (nStationNum == -1)
				{
					m_model.OutputLog(LogLevel.Error, "缺失站号!");
					return null;
				}
				
				if ((x == -1 || y == -1) )
				{
					m_model.OutputLog(LogLevel.Error, "缺失经纬度信息!");
					return null;
				}
				
				if(dtp.m_rs != null)
				{
					dtp.m_rs.beforeFirst();
					while (dtp.m_rs.next())
					{
						alStationInfo.add(new StationInfo( x == -1?-9999:dtp.m_rs.getDouble(x + 1), y == -1?-9999:dtp.m_rs.getDouble(y + 1)
								,h == -1? -9999:dtp.m_rs.getDouble(h + 1),dtp.m_rs.getString(nStationNum + 1)));
					}
				}
				
				else if (dtp.m_list != null)
				{
					for (i = 2; i < dtp.m_list.size(); i++)
		        	{
		        		strs = dtp.m_list.get(i).split(",");
		        		alStationInfo.add(new StationInfo( x == -1?-9999:Double.parseDouble(strs[x]), y == -1? -9999:Double.parseDouble(strs[y]),
		        				h == -1?-9999:Double.parseDouble(strs[h]),strs[nStationNum]));
		        	}
				}
				
			}
			catch(Exception e)
			{
				e.printStackTrace();
				return null;
			}
			return alStationInfo;
		}
		return null;
	}
	
	public void FindBaseStatioNum(StationInfo siReg)
	{
		double dDis = 0;
		TreeMap<Double,StationInfo>  tmSi = new TreeMap<Double,StationInfo>();
		TreeMap<Double,StationInfo>  tm = new TreeMap<Double,StationInfo>();
		for(StationInfo siBase:m_listBaseSI)
		{
			dDis = Math.sqrt((siReg.m_x - siBase.m_x)*(siReg.m_x - siBase.m_x) + (siReg.m_y - siBase.m_y)*(siReg.m_y - siBase.m_y));
			tmSi.put(dDis, siBase);
		}
		
		if (m_eCS.equals(ChooseStation.Last))
		{
			m_strBaseNum =  tmSi.get(tmSi.firstKey()).m_strStationNum;
		}
		
		else
		{
			int index = 0;
			for(double key:tmSi.keySet())
			{
				if (index >= m_iNum)
					break;
				dDis = Math.abs(siReg.m_h - tmSi.get(key).m_h);
				tm.put(dDis, tmSi.get(key));
				index++;
			}
			m_strBaseNum = tm.get(tm.firstKey()).m_strStationNum;
		}
		
		tm.clear();	
		tmSi.clear();
	}
	public boolean Execute()
	{
		try
		{
			m_llResult.clear();
			m_llResult.add("StationNum");
			m_llResult.add("String");
			
			m_listBaseSI = GetData(m_alInputPort.get(0),0);
			StationInfo info = new StationInfo(Double.parseDouble(m_strLongiTude.trim()),Double.parseDouble(m_strLatiTude.trim())
					,Double.parseDouble(m_strHight.trim()),m_strStationNum);
			FindBaseStatioNum(info);
			m_llResult.add(m_strBaseNum);
		}
		
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		OnParamChanged();
		return true;
	}
	
	public int GetOutputParam(Port port ,ArrayList<Param> alParam)
	{
		int i = FindPort(port, false);
		if (i == -1)
			return 0;
		if (i == 0)
			alParam.add(new Param("CSV",m_llResult));
		return alParam.size();
	}
	
	String m_strStationNum = "846506";
	String m_strLongiTude ="123.0";
	String m_strLatiTude ="123.0";
	String m_strHight ="1860";
	String m_strBaseNum ="";
	int m_iNum = 0;
	List<StationInfo> m_listBaseSI;
	List<String> m_llResult;
	
	enum ChooseStation
	{
		Last,
		TowOrThree
	}
	
	ChooseStation m_eCS;
	class  StationInfo
	{
		public double m_x;
		public double m_y;
		public double m_h;
		public String m_strStationNum;
		Date m_dt = new Date();
		
		public StationInfo(double x,double y,double h,String strNum ) throws ParseException
		{
			this.m_x = x;
			this.m_y = y;
			this.m_h = h;
			this.m_strStationNum = strNum;
		}
	}

}
